#include <hi3861_platform.h>
#include <hi_mdm.h>
#include "app_main.h"
#include <hi_io.h>
#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include <hi_flash.h>
#include <hi_nv.h>
#include <hi_lowpower.h>
#include <hi_diag.h>
#include <hi_crash.h>
#include <hi_sal.h>
#include <hi_shell.h>
#include <hi_fs.h>
#include "hi_wifi_api.h"
#include <hi_partition_table.h>
#include <hi_ver.h>
#include <hi_cpu.h>
#include <hi_crash.h>
#include <hi_early_debug.h>
#include <hi_tsensor.h>


#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "cmsis_os2.h"

#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include <hi_i2s.h>
#include <hi_i2c.h>
#include <hi_types_base.h>
#include "wifiiot_i2c.h"
#include "wifiiot_i2c_ex.h"
#include "hos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include "softap.h"
#include "sta.h"
#include <hi_gpio.h>
#define WM8978_DEVICE_ADDR				0X1A	//WM8978的器件地址,固定为0X1A 

#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define ACK_CHECK_EN 0x1            /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0            /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0                    /*!< I2C ack val */
#define NACK_VAL 0x1                /*!< I2C nack val */

hi_u32 g_audio_event;
hi_u8 get_buff1[50][1024];

static unsigned short wm8978_register_tbl[] = {
    0X0000, 0X0000, 0X0000, 0X0000, 0X0050, 0X0000, 0X0140, 0X0000,
    0X0000, 0X0000, 0X0000, 0X00FF, 0X00FF, 0X0000, 0X0100, 0X00FF,
    0X00FF, 0X0000, 0X012C, 0X002C, 0X002C, 0X002C, 0X002C, 0X0000,
    0X0032, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000,
    0X0038, 0X000B, 0X0032, 0X0000, 0X0008, 0X000C, 0X0093, 0X00E9,
    0X0000, 0X0000, 0X0000, 0X0000, 0X0003, 0X0010, 0X0010, 0X0100,
    0X0100, 0X0002, 0X0001, 0X0001, 0X0039, 0X0039, 0X0039, 0X0039,
    0X0001, 0X0001
};





hi_u32 WM8978_Write_Reg(hi_u8 reg, hi_u16 val)
{
    //unsigned char buf[2];
    //buf[0] = (reg<<1)|((val>>8)&0X01);
    //buf[1] = val&0XFF;

    hi_i2c_data i2c_data;
    hi_u8 send_data[2]= { 0 };
    send_data[0] = (reg<<1)|((val>>8)&0X01);
    send_data[1] = val&0XFF;
/* 	send_data[0] = reg;
	send_data[1] = val; */
    i2c_data.send_buf = send_data;
    i2c_data.send_len = 2; 
//(WM8978_DEVICE_ADDR>>1)|0
	wm8978_register_tbl[reg] = val;
   // return hi_i2c_writeread(HI_I2C_IDX_1,(WM8978_DEVICE_ADDR<<1), &i2c_data);
   //hi_i2c_write
   return hi_i2c_write(HI_I2C_IDX_1,(WM8978_DEVICE_ADDR<<1), &i2c_data);
}

hi_u32 WM8978_Read_Reg(hi_u8 reg)
{
    return wm8978_register_tbl[reg];
}




//WM8978 AUXR,AUXL(PWM音频部分)增益设置(AUXR/L-->ADC输入部分的增益)
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
void WM8978_AUX_Gain(hi_u8 gain)
{
	hi_u16 regval;
	gain&=0X07;
	regval=WM8978_Read_Reg(47);	//读取R47
	regval&=~(7<<0);			//清除原来的设置 
 	WM8978_Write_Reg(47,regval|gain<<0);//设置R47
	regval=WM8978_Read_Reg(48);	//读取R48
	regval&=~(7<<0);			//清除原来的设置 
 	WM8978_Write_Reg(48,regval|gain<<0);//设置R48
}  

//WM8978 输出配置 
//dacen:DAC输出(放音)开启(1)/关闭(0)
//bpsen:Bypass输出(录音,包括MIC,LINE IN,AUX等)开启(1)/关闭(0) 
void WM8978_Output_Cfg(hi_u8 dacen,hi_u8 bpsen)
{
	hi_u16 regval=0;
	if(dacen)regval|=1<<0;	//DAC输出使能
	if(bpsen)
	{
		regval|=1<<1;		//BYPASS使能
		regval|=5<<2;		//0dB增益
	} 
	WM8978_Write_Reg(50,regval);//R50设置
	WM8978_Write_Reg(51,regval);//R51设置 
}


//WM8978 MIC增益设置(不包括BOOST的20dB,MIC-->ADC输入部分的增益)
//gain:0~63,对应-12dB~35.25dB,0.75dB/Step
void WM8978_MIC_Gain(hi_u8 gain)
{
	gain&=0X3F;
	WM8978_Write_Reg(45,gain);		//R45,左通道PGA设置 
	WM8978_Write_Reg(46,gain|1<<8);	//R46,右通道PGA设置
}


//WM8978 L2/R2(也就是Line In)增益设置(L2/R2-->ADC输入部分的增益)
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
void WM8978_LINEIN_Gain(hi_u8 gain)
{
	hi_u16 regval;
	gain&=0X07;
	regval=WM8978_Read_Reg(47);	//读取R47
	regval&=~(7<<4);			//清除原来的设置 
 	WM8978_Write_Reg(47,regval|gain<<4);//设置R47
	regval=WM8978_Read_Reg(48);	//读取R48
	regval&=~(7<<4);			//清除原来的设置 
 	WM8978_Write_Reg(48,regval|gain<<4);//设置R48
} 



//WM8978 DAC/ADC配置
//adcen:adc使能(1)/关闭(0)
//dacen:dac使能(1)/关闭(0)
void WM8978_ADDA_Cfg(hi_u8 dacen,hi_u8 adcen)
{
	hi_u16 regval;
	regval=WM8978_Read_Reg(3);	//读取R3
	if(dacen)regval|=3<<0;		//R3最低2个位设置为1,开启DACR&DACL
	else regval&=~(3<<0);		//R3最低2个位清零,关闭DACR&DACL.
	WM8978_Write_Reg(3,regval);	//设置R3
	regval=WM8978_Read_Reg(2);	//读取R2
	if(adcen)regval|=3<<0;		//R2最低2个位设置为1,开启ADCR&ADCL
	else regval&=~(3<<0);		//R2最低2个位清零,关闭ADCR&ADCL.
	WM8978_Write_Reg(2,regval);	//设置R2	
}




//WM8978 输入通道配置 
//micen:MIC开启(1)/关闭(0)
//lineinen:Line In开启(1)/关闭(0)
//auxen:aux开启(1)/关闭(0) 
void WM8978_Input_Cfg(hi_u8 micen,hi_u8 lineinen,hi_u8 auxen)
{
	hi_u16 regval;  
	regval=WM8978_Read_Reg(2);	//读取R2
	if(micen)regval|=3<<2;		//开启INPPGAENR,INPPGAENL(MIC的PGA放大)
	else regval&=~(3<<2);		//关闭INPPGAENR,INPPGAENL.
 	WM8978_Write_Reg(2,regval);	//设置R2 
	
	regval=WM8978_Read_Reg(44);	//读取R44
	if(micen)regval|=3<<4|3<<0;	//开启LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
	else regval&=~(3<<4|3<<0);	//关闭LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
	WM8978_Write_Reg(44,regval);//设置R44
	
	if(lineinen)WM8978_LINEIN_Gain(5);//LINE IN 0dB增益
	else WM8978_LINEIN_Gain(0);	//关闭LINE IN
	if(auxen)WM8978_AUX_Gain(7);//AUX 6dB增益
	else WM8978_AUX_Gain(0);	//关闭AUX输入  
}



//设置I2S工作模式
//fmt:0,LSB(右对齐);1,MSB(左对齐);2,飞利浦标准I2S;3,PCM/DSP;
//len:0,16位;1,20位;2,24位;3,32位;  
void WM8978_I2S_Cfg(hi_u8 fmt,hi_u8 len)
{
	fmt&=0X03;
	len&=0X03;//限定范围
	WM8978_Write_Reg(4,(fmt<<3)|(len<<5));	//R4,WM8978工作模式设置	
}	

//设置耳机左右声道音量
//voll:左声道音量(0~63)
//volr:右声道音量(0~63)
void WM8978_HPvol_Set(hi_u8 voll,hi_u8 volr)
{
	voll&=0X3F;
	volr&=0X3F;//限定范围
	if(voll==0)voll|=1<<6;//音量为0时,直接mute
	if(volr==0)volr|=1<<6;//音量为0时,直接mute 
	WM8978_Write_Reg(52,voll);			//R52,耳机左声道音量设置
	WM8978_Write_Reg(53,volr|(1<<8));	//R53,耳机右声道音量设置,同步更新(HPVU=1)
}
//设置喇叭音量
//voll:左声道音量(0~63) 
void WM8978_SPKvol_Set(hi_u8 volx)
{ 
	volx&=0X3F;//限定范围
	if(volx==0)volx|=1<<6;//音量为0时,直接mute 
 	WM8978_Write_Reg(54,volx);			//R54,喇叭左声道音量设置
	WM8978_Write_Reg(55,volx|(1<<8));	//R55,喇叭右声道音量设置,同步更新(SPKVU=1)	
}




void I2C_TEST()
{
	hi_u32 ret;
 	hi_io_set_func(HI_IO_NAME_GPIO_0, 	HI_IO_FUNC_GPIO_0_I2C1_SDA);
    hi_io_set_func(HI_IO_NAME_GPIO_1, 	HI_IO_FUNC_GPIO_1_I2C1_SCL);

    ret = hi_i2c_deinit(HI_I2C_IDX_1); /* if wake_up from deep sleep, should deinit first */
	    if (ret != HI_ERR_SUCCESS) {
        printf("I2C delete error\r\n");
        return;
    }
    ret = hi_i2c_init(HI_I2C_IDX_1, 100000); /* baudrate: 100000 */
    if (ret != HI_ERR_SUCCESS) {
        printf("I2C error\r\n");
        return;
    }
	
	printf("IIC sucessfully\r\n");
	ret = WM8978_Write_Reg(0,0);
	  if (ret != HI_ERR_SUCCESS) {
        printf("8978 error\r\n");
		printf("flash partition table init fail:0x%x \r\n", ret);
        return;
    }
	printf("8978 pass\r\n");
}





unsigned int wm8978_init(void)
{   

	hi_u32 ret;
  	hi_io_set_func(HI_IO_NAME_GPIO_0, 	HI_IO_FUNC_GPIO_0_I2C1_SDA);
    hi_io_set_func(HI_IO_NAME_GPIO_1, 	HI_IO_FUNC_GPIO_1_I2C1_SCL);
	
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_I2S0_MCLK);
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2S0_TX);
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_I2S0_RX);
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_I2S0_BCLK);
    hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2S0_WS);



    ret = hi_i2s_deinit();  /* if wake_up from deep sleep, should deinit first */
    hi_i2s_attribute i2s_cfg = {
        .sample_rate = HI_I2S_SAMPLE_RATE_16K,
        .resolution = HI_I2S_RESOLUTION_16BIT,
    };
	if (ret != HI_ERR_SUCCESS) {
        printf("Failed to deinit i2s!\n");
    }
    ret = hi_i2s_init(&i2s_cfg);
    if (ret != HI_ERR_SUCCESS) {
       printf("I2s init error!\n");
    }

	printf("I2s init success!\n");



 
    ret = hi_i2c_deinit(HI_I2C_IDX_1); /* if wake_up from deep sleep, should deinit first */
	    if (ret != HI_ERR_SUCCESS) {
        printf("I2C delete error\r\n");
        return;
    }
    ret = hi_i2c_init(HI_I2C_IDX_1, 100000); /* baudrate: 100000 */
    if (ret != HI_ERR_SUCCESS) {
        printf("I2C error\r\n");
        return;
    }
	
	printf("IIC sucessfully\r\n");


	ret = WM8978_Write_Reg(0,0);
	  if (ret != HI_ERR_SUCCESS) {
        printf("8978 error\r\n");
		printf("flash partition table init fail:0x%x \r\n", ret);
        return;
    }
	usleep(20*1000);

	WM8978_Write_Reg(1,0X1B);	//R1,MICEN设置为1(MIC使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为:11(5K)
	WM8978_Write_Reg(2,0X1B0);	//R2,ROUT1,LOUT1输出使能(耳机可以工作),BOOSTENR,BOOSTENL使能
	WM8978_Write_Reg(3,0X6C);	//R3,LOUT2,ROUT2输出使能(喇叭工作),RMIX,LMIX使能	
	WM8978_Write_Reg(6,0);		//R6,MCLK由外部提供
	WM8978_Write_Reg(43,1<<4);	//R43,INVROUT2反向,驱动喇叭
	WM8978_Write_Reg(47,1<<8);	//R47设置,PGABOOSTL,左通道MIC获得20倍增益
	WM8978_Write_Reg(48,1<<8);	//R48设置,PGABOOSTR,右通道MIC获得20倍增益
	WM8978_Write_Reg(49,1<<1);	//R49,TSDEN,开启过热保护 
	WM8978_Write_Reg(10,1<<3);	//R10,SOFTMUTE关闭,128x采样,最佳SNR 
	WM8978_Write_Reg(14,1<<3);	//R14,ADC 128x采样率

	
    WM8978_ADDA_Cfg(1,1);
    WM8978_Input_Cfg(1,0,0);
    WM8978_Output_Cfg(1,0);

    WM8978_MIC_Gain(60);
    WM8978_LINEIN_Gain(0);
	WM8978_SPKvol_Set(60);		//喇叭音量设置
    WM8978_HPvol_Set(0,0);
	WM8978_I2S_Cfg(2,0);


	
}

hi_u8 audio_flag;
hi_u8 key_dat;




void Recode()
{
	hi_u32 ret,i,j;
	hi_u8 pcm_num;
	printf("begin recode\r\n");
	usleep(500*1000);
	for(pcm_num=0;pcm_num<50;pcm_num++)
	{
		 ret = hi_i2s_read(get_buff1[pcm_num],1024,HI_SYS_WAIT_FOREVER);
	}

	printf("player the audio\r\n");

		for(pcm_num=0;pcm_num<50;pcm_num++)
	{
		 ret = hi_i2s_write(get_buff1[pcm_num],1024,HI_SYS_WAIT_FOREVER);
	}
	audio_flag=2;

}

void Audio_TEST(void)
{
    hi_u32 ret,i,j;
	hi_u8 pcm_num;
	hi_gpio_value gpio_val = HI_GPIO_VALUE1;

	usleep(30*1000);
    wm8978_init();
	usleep(30*1000);

	audio_flag=1;
	while(audio_flag==1)
	{
		osDelay(1000);
	}

   Recode();
	

    while (1)
    {
/*      hi_i2s_read(get_buff,4,1000);
        printf("%d %d %d %d\r\n",get_buff[0],get_buff[1],get_buff[2],get_buff[3]);  */
        osDelay(130*1000);
    }

}